package com.bango.android;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.http.message.BasicNameValuePair;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;

public class BangoDatabaseStorage extends SQLiteOpenHelper
{
	public class ProfilePersistent
	{
		public Date Date;
		public String BangoUserId;
		
	}
	private SQLiteDatabase _database;

	private int _profileId;

	private boolean _persistDatabaseConnection;
	private boolean _openLogProfile;
	private boolean _openUpdateProfileLocation;
	private boolean _openLogEvent;
	private boolean _openProfilesForPost;
	private boolean _openEventsForPost;
	private boolean _openEventsPosted;
	private boolean _openDeleteEventsPosted;
	private final Object lockObject;
	

	public int ProfileId()
	{
		return _profileId;
	}
	
	public boolean PersistDatabaseConnection()
	{
		return _persistDatabaseConnection;
	}

	public void PersistDatabaseConnection(boolean persistDatabaseConnection)
	{
		_persistDatabaseConnection = persistDatabaseConnection;
	}

	private String ProfileTableName()
	{
		return BangoConstants.DATABASE_TABLENAMEPROFILE + "_" + Integer.toString(BangoConstants.DATABASE_VERSION);
	}

	private String EventTableName()
	{
		return BangoConstants.DATABASE_TABLENAMEEVENT + "_" + Integer.toString(BangoConstants.DATABASE_VERSION);
	}

	private String EventParameterTableName()
	{
		return BangoConstants.DATABASE_TABLENAMEEVENTPARAMETER + "_" + Integer.toString(BangoConstants.DATABASE_VERSION);
	}
	
	private String ProfilePersistentTableName()
	{
		return BangoConstants.DATABASE_TABLENAMEPROFILEPERSISTENT + "_" + Integer.toString(BangoConstants.DATABASE_VERSION);
	}

	BangoDatabaseStorage(Context context)
	{
		this(context, null);
	
	}
	
	BangoDatabaseStorage(Context context, Object synchronisationObject)
	{
		super(context, BangoConstants.DATABASE_NAME, null, BangoConstants.DATABASE_VERSION);
		
		if (null == synchronisationObject)
		{ 
			lockObject = new Object(); 
		}
		else 
		{ 
			lockObject = synchronisationObject; 
		}
		
		_openLogProfile = false;
		_openUpdateProfileLocation = false;
		_openLogEvent = false;
		_openProfilesForPost = false;
		_openEventsForPost = false;
		_openEventsPosted = false;
		_openDeleteEventsPosted = false;
	}

	@Override public void onOpen(SQLiteDatabase db)
	{		
		_database = db;
		CreateTables();
	}

	@Override public void onCreate(SQLiteDatabase db)
	{
		
	}

	@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
	{
		synchronized (lockObject) {
			DropTables();
		}
	}	

	private void OpenDatabase()
	{
		OpenDatabase(false);
	}

	private void OpenDatabase(boolean forceOpen)
	{
		boolean openDb = false;

		if (_database != null)
		{
			if (forceOpen || !_database.isOpen())
			{
				openDb = true;
			}
		}
		else
		{
			openDb = true;
		}

		if (openDb)
		{
			try			
			{			
				_database = getWritableDatabase();
			}
			catch(Exception ex)
			{
			}
		}

	}
	
	public void CloseDatabase(boolean ignorePersistConnection)
	{
		if (ignorePersistConnection || !PersistDatabaseConnection())
		{			
				CloseDatabase();		
		}
	}

	private void CloseDatabase()
	{
		if (_database != null)
		{
			try
			{
				if (_database.isOpen() && !_openLogProfile && !_openUpdateProfileLocation && !_openLogEvent && !_openProfilesForPost && !_openEventsForPost && !_openEventsPosted && !_openDeleteEventsPosted)
				{
					_database.close();
				}
	
				/*
				 * Database.close causes illegal state exception when using non
				 * persistent connections. It doesn't seem to reset the reference
				 * count for the SQLiteDatabase object to zero. To work around, set
				 * the database to null. If changed, also change
				 * OpenDatabase(boolean)
				 */
				_database = null;
			}
			catch(Exception ex)
			{
			}
		}
	}


	private void CreateTables()
	{		
		_database.execSQL(BangoConstants.DATABASE_TABLECREATEPROFILE.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, ProfileTableName()));
		_database.execSQL(BangoConstants.DATABASE_TABLECREATEEVENT.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, EventTableName()));
		_database.execSQL(BangoConstants.DATABASE_TABLECREATEEVENTPARAMETER.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, EventParameterTableName()));
		_database.execSQL(BangoConstants.DATABASE_TABLECREATEPROFILEPERSISTENT.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, ProfilePersistentTableName()));

		CompactDatabase();
	}

	private void DropTables()
	{		
		OpenDatabase();			
		Cursor tableNames = _database.rawQuery(BangoConstants.DATABASE_SELECTTABLES, null);
		try
		{
			String tableName;
			if (tableNames != null)
			{
				if (tableNames.moveToFirst())
				{
					do
					{
						tableName = tableNames.getString(0);
						_database.execSQL("DROP TABLE IF EXISTS [" + tableName + "]");
					}
					while (tableNames.moveToNext());
				}
				tableNames.close();
			}				
			CreateTables();	
		}
		catch (Exception ex)
		{
			if (tableNames != null && !tableNames.isClosed())
			{
				tableNames.close();
			}
		}
		finally
		{
			CloseDatabase(false);
		}
	
	}

	private void CompactDatabase()
	{
		_database.execSQL("VACUUM;");
	}
	
	public void LogProfile(BangoProfile bangoProfile)
	{
		LogProfile(bangoProfile.SdkType(), bangoProfile.SdkVersion(), bangoProfile.ApplicationId(), bangoProfile.ApplicationType(), bangoProfile.ApplicationChannel(), 
				bangoProfile.ApplicationVersion(), bangoProfile.UserId(), bangoProfile.SessionRestartTime(), bangoProfile.ConnectionType(), bangoProfile.IsRoaming(),
				bangoProfile.LocationSource(), bangoProfile.LocationAltitude(), bangoProfile.LocationLatitude(), bangoProfile.LocationLongitude(), bangoProfile.LocationAccuracy(),
				bangoProfile.Operator(), bangoProfile.OperatorName(), bangoProfile.OperatorCountryIso(), bangoProfile.SimOperator(), bangoProfile.Brand(), bangoProfile.Device(), 
				bangoProfile.Model(), bangoProfile.Product(), bangoProfile.Version(), bangoProfile.BuildId(), bangoProfile.OperatorConnectionType(), bangoProfile.BangoUserId());
	}
	
	public void LogProfile(int sdkType, String sdkVersion, String applicationId, String applicationType, String applicationChannel, String applicationVersion, String userId, int sessionRestartTime, int connectionType, boolean isRoaming, String locationSource, double locationAltitude, double locationLatitude, double locationLongitude, float locationAccuracy, String operator, String operatorName, String operatorCountryIso, String simOperator, String brand, String device, String model, String product, String version, String buildId, int operatorConnectionType, String bangoUserId)
	{
		SQLiteStatement insertProfileStatement;
		
		int isRoamingInt = isRoaming ? 1 : 0;

		if (applicationId == null)
		{
			applicationId = "";
		}

		if (applicationType == null)
		{
			applicationType = "";
		}

		if (applicationChannel == null)
		{
			applicationChannel = "";
		}

		if (applicationVersion == null)
		{
			applicationVersion = "";
		}

		if (userId == null)
		{
			userId = "";
		}

		if (locationSource == null)
		{
			locationSource = "";
		}

		if (operator == null)
		{
			operator = "";
		}

		if (operatorCountryIso == null)
		{
			operatorCountryIso = "";
		}

		if (simOperator == null)
		{
			simOperator = "";
		}

		if (brand == null)
		{
			brand = "";
		}

		if (device == null)
		{
			device = "";
		}

		if (model == null)
		{
			model = "";
		}

		if (product == null)
		{
			product = "";
		}

		if (version == null)
		{
			version = "";
		}

		if (buildId == null)
		{
			buildId = "";
		}
		
		LogProfilePersistent(bangoUserId);
		
		_openLogProfile = true;

		synchronized (lockObject) {
			try
			{
				OpenDatabase();
								
				insertProfileStatement = _database.compileStatement(BangoConstants.DATABASE_CREATEPROFILE.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, ProfileTableName()));
					
				insertProfileStatement.clearBindings();
		
				insertProfileStatement.bindLong(1, sdkType);
				insertProfileStatement.bindString(2, sdkVersion);
				insertProfileStatement.bindString(3, applicationId);
				insertProfileStatement.bindString(4, applicationType);
				insertProfileStatement.bindString(5, applicationChannel);
				insertProfileStatement.bindString(6, applicationVersion);
		
				insertProfileStatement.bindString(7, userId);
		
				insertProfileStatement.bindLong(8, sessionRestartTime);
				insertProfileStatement.bindLong(9, connectionType);
				insertProfileStatement.bindLong(10, isRoamingInt);
		
				insertProfileStatement.bindString(11, locationSource);
				insertProfileStatement.bindDouble(12, locationAltitude);
				insertProfileStatement.bindDouble(13, locationLatitude);
				insertProfileStatement.bindDouble(14, locationLongitude);
				insertProfileStatement.bindDouble(15, locationAccuracy);
		
				insertProfileStatement.bindString(16, operator);
				insertProfileStatement.bindString(17, operatorName);
				insertProfileStatement.bindString(18, operatorCountryIso);
				insertProfileStatement.bindString(19, simOperator);
				insertProfileStatement.bindString(20, brand);
				insertProfileStatement.bindString(21, device);
				insertProfileStatement.bindString(22, model);
				insertProfileStatement.bindString(23, product);
				insertProfileStatement.bindString(24, version);
				insertProfileStatement.bindString(25, buildId);
		
				insertProfileStatement.bindLong(26, operatorConnectionType);
				insertProfileStatement.bindLong(27, 0);
				
				_profileId = (int) insertProfileStatement.executeInsert();
			}
			catch(Exception ex)
			{
			}
			finally
			{	
				_openLogProfile = false;
				CloseDatabase(false);
			}
			
		}
	}
	
	public void LogProfilePersistent(String bangoUserId)
	{
		SQLiteStatement insertUpdateProfileStatement;
		String currentBangoUserId = null;
		
		if(bangoUserId != null){
			_openLogProfile = true;
			
			synchronized (lockObject) {
				try
				{
					OpenDatabase();
					
					Cursor profilePersistent = null;

					profilePersistent = _database.rawQuery(BangoConstants.DATABASE_SELECTPOSTPROFILESPERSISTENT.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, ProfilePersistentTableName()), new String[]{});
					if (profilePersistent != null)
					{
						if (profilePersistent.moveToFirst()) {
							currentBangoUserId = profilePersistent.getString(profilePersistent.getColumnIndex(BangoConstants.DATABASE_COLUMN_BANGOUSERID));
						}
						profilePersistent.close();
					}

					if(!bangoUserId.equals(currentBangoUserId))
					{
						//Delete the old bango user id
						_database.execSQL(BangoConstants.DATABASE_DELETEPROFILEPERSISTENT.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, ProfilePersistentTableName()));						
						
						insertUpdateProfileStatement = _database.compileStatement(BangoConstants.DATABASE_CREATEPROFILEPERSISTENT.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, ProfilePersistentTableName()));
						
						insertUpdateProfileStatement.clearBindings();
				
						insertUpdateProfileStatement.bindString(1, bangoUserId);
						insertUpdateProfileStatement.bindLong(2, new Date(System.currentTimeMillis()).getTime());
						
						insertUpdateProfileStatement.executeInsert();
					}
				}
				catch(Exception ex)
				{
				}
				finally
				{	
					_openLogProfile = false;
					CloseDatabase(false);
				}
			}			
		}
	}

	public void UpdateProfileLocation(String locationSource, double locationLatitude, double locationLongitude, double locationAltitude, float locationAccuracy)
	{
		
		_openUpdateProfileLocation = true;
		
		synchronized (lockObject) {
				
			try
			{
				OpenDatabase();		
				_database.execSQL(BangoConstants.DATABASE_UPDATEPROFILELOCATION.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, ProfileTableName()).replace(BangoConstants.DATABASE_PARAMETER1_PLACEHOLDER, Double.toString(locationLatitude)).replace(BangoConstants.DATABASE_PARAMETER2_PLACEHOLDER, Double.toString(locationLongitude)).replace(BangoConstants.DATABASE_PARAMETER3_PLACEHOLDER, Double.toString(locationAltitude)).replace(BangoConstants.DATABASE_PARAMETER4_PLACEHOLDER, Double.toString(locationAccuracy)).replace(BangoConstants.DATABASE_PARAMETER5_PLACEHOLDER, locationSource) + Integer.toString(_profileId));
			}
			catch(Exception ex)
			{
				
			}
			finally
			{
				_openUpdateProfileLocation = false;
				CloseDatabase(false);
			}
		}
	}

	public int LogEvent (BangoEvent bangoEvent)
	{
		return LogEvent(bangoEvent.ConnectionType(), bangoEvent.OperatorConnectionType(), bangoEvent.ErrorLevel(), bangoEvent.EventName(), bangoEvent.EventDetail(), 
				bangoEvent.EventValue(), bangoEvent.ErrorId(), bangoEvent.EventTime(), bangoEvent.EventLocalTime(), bangoEvent.EventParameters());
	}
	
	public int LogEvent(int connectionType, int operatorConnectionType, int errorLevel, String eventName, String eventDetail, String eventValue, String errorId, Date eventTime, Date eventLocalTime, List<BasicNameValuePair> eventParameters)
	{
		SQLiteStatement insertEventStatement;

		int eventId = -1;

		if (eventName == null)
		{
			eventName = "";
		}

		if (eventDetail == null)
		{
			eventDetail = "";
		}

		if (eventValue == null)
		{
			eventValue = "";
		}

		if (errorId == null)
		{
			errorId = "";
		}
		
		_openLogEvent = true;		
		
		synchronized (lockObject) {
			try
			{
				OpenDatabase();
			
				insertEventStatement = _database.compileStatement(BangoConstants.DATABASE_CREATEEVENT.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, EventTableName()));
									
				insertEventStatement.clearBindings();
		
				insertEventStatement.bindLong(1, _profileId);
				insertEventStatement.bindString(2, eventName);
				insertEventStatement.bindString(3, eventDetail);
				insertEventStatement.bindString(4, eventValue);
				insertEventStatement.bindString(5, errorId);
				insertEventStatement.bindLong(6, eventTime.getTime());
				insertEventStatement.bindLong(7, eventLocalTime.getTime());
				insertEventStatement.bindLong(8, connectionType);
				insertEventStatement.bindLong(9, operatorConnectionType);
				insertEventStatement.bindLong(10, errorLevel);
				insertEventStatement.bindLong(11, 0);
	
				eventId = (int) insertEventStatement.executeInsert();
				LogEventParameter(eventId, eventParameters);
			}
			catch(Exception ex)
			{
			}
			finally
			{
				_openLogEvent = false;
				CloseDatabase(false);
			}
		}
		return eventId;
	}

	private void LogEventParameter(int eventId, List<BasicNameValuePair> eventParameters)
	{
		SQLiteStatement insertEventParameterStatement;
		BasicNameValuePair eventParameter;
		String eventParameterName;
		String eventParameterValue;
		if (eventParameters != null)
		{
			insertEventParameterStatement = _database.compileStatement(BangoConstants.DATABASE_CREATEEVENTPARAMETER.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, EventParameterTableName()));
			
			for (Iterator<BasicNameValuePair> eventParameterIterator = eventParameters.iterator(); eventParameterIterator.hasNext();)
			{
				insertEventParameterStatement.clearBindings();

				eventParameter = eventParameterIterator.next();
				eventParameterName = eventParameter.getName();
				eventParameterValue = eventParameter.getValue();

				if (eventParameterName == null)
				{
					eventParameterName = "";
				}

				if (eventParameterValue == null)
				{
					eventParameterValue = "";
				}

				insertEventParameterStatement.bindLong(1, eventId);
				insertEventParameterStatement.bindString(2, eventParameterName);
				insertEventParameterStatement.bindString(3, eventParameterValue);

				insertEventParameterStatement.executeInsert();

			}
		}
	}

	public List<BangoProfile> GetProfilesForPost(boolean notCurrentProfile, String applicationIdForProfile, String bangoUserId)
	{
		int notProfileId = 0;
		List<BangoProfile> returnValue = new ArrayList<BangoProfile>();
		BangoProfile bangoProfile;
		Cursor profiles = null;
		int profileId;
		int sdkType;
		int sdkVersion;
		int applicationId;
		int applicationType;
		int applicationChannel;
		int applicationVersion;
		int userId;
		int sessionRestartTime;
		int connectionType;
		int isRoaming;
		int locationSource;
		int locationAltitude;
		int locationLatitude;
		int locationLongitude;
		int locationAccuracy;
		int operator;
		int operatorName;
		int operatorCountryIso;
		int simOperator;
		int brand;
		int device;
		int model;
		int product;
		int version;
		int buildId;
		int operatorConnectionType;
		
		if (notCurrentProfile)
		{
			notProfileId = _profileId;
		}
		
		_openProfilesForPost = true;
		
		synchronized (lockObject) {
			OpenDatabase();
	
			try
			{
				if ((null == applicationIdForProfile) || (applicationIdForProfile.equals("")))
				{
					profiles = _database.rawQuery(BangoConstants.DATABASE_SELECTPOSTPROFILES_ALL.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, ProfileTableName()), new String[] { Integer.toString(notProfileId) });					
				}
				else 
				{
					profiles = _database.rawQuery(BangoConstants.DATABASE_SELECTPOSTPROFILES.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, ProfileTableName()), new String[] { Integer.toString(notProfileId), applicationIdForProfile });
				}

				if (profiles != null)
				{
					if (profiles.moveToFirst())
					{
	
						profileId = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_PROFILEID);
						sdkType = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_SDKTYPE);
						sdkVersion = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_SDKVERSION);
						applicationId = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_APPLICATIONID);
						applicationType = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_APPLICATIONTYPE);
						applicationChannel = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_APPLICATIONCHANNEL);
						applicationVersion = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_APPLICATIONVERSION);
						userId = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_USERID);
						sessionRestartTime = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_SESSIONRESTARTTIME);
						connectionType = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_CONNECTIONTYPE);
						isRoaming = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_ISROAMING);
						locationSource = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_LOCATIONSOURCE);
						locationAltitude = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_LOCATIONALTITUDE);
						locationLatitude = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_LOCATIONLATITUDE);
						locationLongitude = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_LOCATIONLONGITUDE);
						locationAccuracy = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_LOCATIONACCURACY);
						operator = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_OPERATOR);
						operatorName = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_OPERATORNAME);
						operatorCountryIso = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_OPERATORCOUNTRYISO);
						simOperator = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_SIMOPERATOR);
						brand = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_BRAND);
						device = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_DEVICE);
						model = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_MODEL);
						product = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_PRODUCT);
						version = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_VERSION);
						buildId = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_BUILDID);
						operatorConnectionType = profiles.getColumnIndex(BangoConstants.DATABASE_COLUMN_OPERATORCONNECTIONTYPE);
						do
						{
							bangoProfile = new BangoProfile();
							bangoProfile.ProfileId(profiles.getInt(profileId));
							bangoProfile.SdkType(profiles.getInt(sdkType));
							bangoProfile.SdkVersion(profiles.getString(sdkVersion));
							bangoProfile.ApplicationId(profiles.getString(applicationId));
							bangoProfile.ApplicationType(profiles.getString(applicationType));
							bangoProfile.ApplicationChannel(profiles.getString(applicationChannel));
							bangoProfile.ApplicationVersion(profiles.getString(applicationVersion));
							bangoProfile.UserId(profiles.getString(userId));
							bangoProfile.SessionRestartTime(profiles.getInt(sessionRestartTime));
							bangoProfile.ConnectionType(profiles.getInt(connectionType));
							bangoProfile.IsRoaming(profiles.getInt(isRoaming) == 0 ? false : true);
							bangoProfile.LocationSource(profiles.getString(locationSource));
							bangoProfile.LocationAltitude(profiles.getDouble(locationAltitude));
							bangoProfile.LocationLatitude(profiles.getDouble(locationLatitude));
							bangoProfile.LocationLongitude(profiles.getDouble(locationLongitude));
							bangoProfile.LocationAccuracy(profiles.getFloat(locationAccuracy));
							bangoProfile.Operator(profiles.getString(operator));
							bangoProfile.OperatorName(profiles.getString(operatorName));
							bangoProfile.OperatorCountryIso(profiles.getString(operatorCountryIso));
							bangoProfile.SimOperator(profiles.getString(simOperator));
							bangoProfile.Brand(profiles.getString(brand));
							bangoProfile.Device(profiles.getString(device));
							bangoProfile.Model(profiles.getString(model));
							bangoProfile.Product(profiles.getString(product));
							bangoProfile.Version(profiles.getString(version));
							bangoProfile.BuildId(profiles.getString(buildId));
							bangoProfile.OperatorConnectionType(profiles.getInt(operatorConnectionType));
							
							bangoProfile.BangoUserId(bangoUserId);
	
							returnValue.add(bangoProfile);
	
						}
						while (profiles.moveToNext());
					}
					profiles.close();
				}
			}
			catch (Exception ex)
			{
				if (profiles != null && !profiles.isClosed())
				{
					profiles.close();
				}
			}
	
			_openProfilesForPost = false;
			CloseDatabase(false);
		}
		return returnValue;

	}
	
	
	public ProfilePersistent GetProfilePersistent()
	{
		
		Cursor profilePersistent = null;
		ProfilePersistent returnValue = new ProfilePersistent();
		returnValue.Date = new Date(System.currentTimeMillis() - 1);
		
		synchronized (lockObject) {
		try
		{
			OpenDatabase();
			
			profilePersistent = _database.rawQuery(BangoConstants.DATABASE_SELECTPOSTPROFILESPERSISTENT.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, ProfilePersistentTableName()), new String[] {});
			
			if (profilePersistent != null)
			{
				if (profilePersistent.moveToFirst())
				{
					returnValue.BangoUserId = profilePersistent.getString(profilePersistent.getColumnIndex(BangoConstants.DATABASE_COLUMN_BANGOUSERID)); 
					returnValue.Date = new Date(profilePersistent.getLong(profilePersistent.getColumnIndex(BangoConstants.DATABASE_COLUMN_DATE)) + BangoConstants.SETTING_BANGOUSERID_EXPIRY_MILLISECONDS);
				}
				profilePersistent.close();
			}
		}
		catch(Exception ex)
		{
			if(profilePersistent != null && !profilePersistent.isClosed()) profilePersistent.close();
		}
		CloseDatabase(false);
		}
				
		return returnValue;
	}
	
	
	
	public ArrayList<BangoEvent> GetEventsForPost(int profileId)
	{
		ArrayList<BangoEvent> returnValue = new ArrayList<BangoEvent>();
		BangoEvent bangoEvent;
		ArrayList<BasicNameValuePair> bangoEventParameters;
		Cursor events = null;
		Cursor eventParameters = null;

		int eventId;
		int eventName;
		int eventDetail;
		int eventValue;
		int errorId;
		int eventTime;
		int eventLocalTime;
		int connectionType;
		int operatorConnectionType;
		int errorLevel;
		
		int eventParameterName;
		int eventParameterValue;
		
		synchronized (lockObject) {
			try
			{
				OpenDatabase();
				_openEventsForPost = true;
				
				_database.execSQL(BangoConstants.DATABASE_UPDATE_EVENT_POSTING.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, EventTableName()) + Integer.toString(profileId));
				events = _database.rawQuery(BangoConstants.DATABASE_SELECTPOSTEVENTS.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, EventTableName()), new String[] { Integer.toString(profileId) });
					
				
				if (events != null)
				{
					if (events.moveToFirst())
					{
						profileId = events.getColumnIndex(BangoConstants.DATABASE_COLUMN_PROFILEID);
						eventId = events.getColumnIndex(BangoConstants.DATABASE_COLUMN_EVENTID);
						eventName = events.getColumnIndex(BangoConstants.DATABASE_COLUMN_EVENTNAME);
						eventDetail = events.getColumnIndex(BangoConstants.DATABASE_COLUMN_EVENTDETAIL);
						eventValue = events.getColumnIndex(BangoConstants.DATABASE_COLUMN_EVENTVALUE);
						errorId = events.getColumnIndex(BangoConstants.DATABASE_COLUMN_ERRORID);
						eventTime = events.getColumnIndex(BangoConstants.DATABASE_COLUMN_EVENTTIME);
						eventLocalTime = events.getColumnIndex(BangoConstants.DATABASE_COLUMN_EVENTLOCALTIME);
						connectionType = events.getColumnIndex(BangoConstants.DATABASE_COLUMN_CONNECTIONTYPE);
						operatorConnectionType = events.getColumnIndex(BangoConstants.DATABASE_COLUMN_OPERATORCONNECTIONTYPE);
						errorLevel = events.getColumnIndex(BangoConstants.DATABASE_COLUMN_ERRORLEVEL);
						do
						{
							bangoEvent = new BangoEvent();
							bangoEvent.ProfileId(events.getInt(profileId));
							bangoEvent.EventId(events.getInt(eventId));
							bangoEvent.EventName(events.getString(eventName));
							bangoEvent.EventDetail(events.getString(eventDetail));
							bangoEvent.EventValue(events.getString(eventValue));
							bangoEvent.ErrorId(events.getString(errorId));
							bangoEvent.EventTime(new Date(events.getLong(eventTime)));
							bangoEvent.EventLocalTime(new Date(events.getLong(eventLocalTime)));
							bangoEvent.ConnectionType(events.getInt(connectionType));
							bangoEvent.OperatorConnectionType(events.getInt(operatorConnectionType));
							bangoEvent.ErrorLevel(events.getInt(errorLevel));
							bangoEvent.EventParameters();
	
							eventParameters = _database.rawQuery(BangoConstants.DATABASE_SELECTPOSTEVENTPARAMETERS.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, EventParameterTableName()), new String[] { Integer.toString(bangoEvent.EventId()) });
							if (eventParameters != null)
							{
								if (eventParameters.moveToFirst())
								{
									eventParameterName = eventParameters.getColumnIndex(BangoConstants.DATABASE_COLUMN_EVENTNAME);
									eventParameterValue = eventParameters.getColumnIndex(BangoConstants.DATABASE_COLUMN_EVENTVALUE);
									bangoEventParameters = new ArrayList<BasicNameValuePair>();
									do
									{
										bangoEventParameters.add(new BasicNameValuePair(eventParameters.getString(eventParameterName), eventParameters.getString(eventParameterValue)));
									}
									while (eventParameters.moveToNext());
									bangoEvent.EventParameters(bangoEventParameters);
								}
								eventParameters.close();
							}
							returnValue.add(bangoEvent);
						}
						while (events.moveToNext());
					}
					events.close();
				}
	
			}
			catch (Exception ex)
			{					
				_database.execSQL(BangoConstants.DATABASE_UPDATE_EVENT_NOT_POSTED.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, EventTableName()) + Integer.toString(profileId));				
				if (events != null && !events.isClosed())
				{									
					events.close();
				}
	
				if (eventParameters != null && !eventParameters.isClosed())
				{
					eventParameters.close();
				}
	
			}
			finally
			{
				_openEventsForPost = false;
				CloseDatabase(false);
			}
		}

		return returnValue;

	}
	
	public boolean DeleteOrphannedRecords()
	{
		boolean returnValue = false;

		try
		{
			OpenDatabase();
			// _database.beginTransaction();
			_database.execSQL(BangoConstants.DATABASE_DELETEORPHANEVENT.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, 
					EventTableName()).replace(BangoConstants.DATABASE_TABLE_JOINPLACEHOLDER, ProfileTableName()));
			_database.execSQL(BangoConstants.DATABASE_DELETEORPHANEVENTPARAMETER.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, 
					EventParameterTableName()).replace(BangoConstants.DATABASE_TABLE_JOINPLACEHOLDER, EventTableName()));
			// _database.setTransactionSuccessful();
		}
		catch (Exception ex)
		{
		}
		finally
		{
			// _database.endTransaction();
			CloseDatabase(false);
		}
		return returnValue;
	}

	public boolean UpdateEventsPosted(int profileId)
	{
		boolean returnValue = false;
		
		_openEventsPosted = true;

		synchronized (lockObject) {	
			try
			{
				OpenDatabase();
				// _database.beginTransaction();
				_database.execSQL(BangoConstants.DATABASE_UPDATEEVENTPOSTED.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, EventTableName()) + Integer.toString(profileId));
				_database.execSQL(BangoConstants.DATABASE_UPDATEPROFILEPOSTED.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, ProfileTableName()) + Integer.toString(profileId));
				// _database.setTransactionSuccessful();
			}
			catch (Exception ex)
			{
			}
			finally
			{
				// _database.endTransaction();
				_openEventsPosted = false;
				CloseDatabase(false);
			}
		}
		
		return returnValue;
	}
	
	public boolean UpdateEventsNotPosted(int profileId)
	{
		boolean returnValue = false;
		
		_openEventsPosted = true;

		synchronized (lockObject) {	
			try
			{
				OpenDatabase();		
				_database.execSQL(BangoConstants.DATABASE_UPDATE_EVENT_NOT_POSTED.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, EventTableName()) + Integer.toString(profileId));				
			}
			catch (Exception ex)
			{
			}
			finally
			{
				_openEventsPosted = false;
				CloseDatabase(false);
			}
		}
		
		return returnValue;
	}
	
	

	public boolean DeleteEventsPosted(int profileId)
	{
		boolean returnValue = false;
		
		_openDeleteEventsPosted = true;
		Cursor profiles = null;
		synchronized (lockObject) {
			try
			{
				OpenDatabase();
				// _database.beginTransaction();
				_database.execSQL(BangoConstants.DATABASE_DELETEEVENTPARAMETER.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, EventParameterTableName()).replace(BangoConstants.DATABASE_TABLE_JOINPLACEHOLDER, EventTableName()).replace(BangoConstants.DATABASE_PARAMETER1_PLACEHOLDER, Integer.toString(profileId)));
				_database.execSQL(BangoConstants.DATABASE_DELETEEVENT.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, EventTableName()) + Integer.toString(profileId));
				
				profiles = _database.rawQuery(BangoConstants.DATABASE_SELECTHASEVENTS.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, EventTableName()), new String[] { Integer.toString(profileId) });					
				
				if (profiles.moveToFirst())
				{
					_database.execSQL(BangoConstants.DATABASE_DELETEPROFILE.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, ProfileTableName()) + Integer.toString(profileId));
				}
				else 
				{
					_database.execSQL(BangoConstants.DATABASE_DELETEPROFILE_FORCE.replace(BangoConstants.DATABASE_TABLE_PLACEHOLDER, ProfileTableName()) + Integer.toString(profileId));
				}
				profiles.close();
				// _database.setTransactionSuccessful();
			}
			catch (Exception ex)
			{
			}
			finally
			{
				// _database.endTransaction();
				if (profiles != null && !profiles.isClosed())
				{
					profiles.close();
				}
				
				_openDeleteEventsPosted = false;
				CloseDatabase(false);
			}
		}
		return returnValue;

	}
}
